//! $Id$
//!
//! @File    ValueContext.h
//! @Author  Johan Andersson <skagget77@gmail.com>
//! @Date    Thu Oct 01 20:22 2009
//! @Ingroup IoCppDetail
//!

#if !defined(IOCPP_VALUECONTEXT_H)
#define IOCPP_VALUECONTEXT_H

#include "IoCpp/Injector.h"
#include "IoCpp/Detail/NamedProvider.h"
#include "IoCpp/Detail/ResolverCache.h"

#include <boost/bind.hpp>
#include <string>

namespace IoCpp
{
namespace Detail
{
   //!
   //! Proxy that represent a constant value as a value provider.
   //!
   //! @param  constant The constant value.
   //!
   //! @return The constant value.
   //!
   template<class T1>
   T1 ConstantProxy( T1 constant ) {
      return constant;
   }


   //!
   //! @author  Johan Andersson <skagget77@gmail.com>
   //! @date    Thu Oct 01 20:22 2009
   //! @ingroup IoCppDetail
   //!
   //! The ValueContext class, holds the state of the configuration while
   //! binding a value.
   //!
   template<class T1>
   class ValueContext
   {
   public :
      //!
      //! Creates a new instance of the ValueContext class.
      //!
      //! @param injector The container's Injector.
      //!
      //! @param name The name of the value being bound.
      //!
      ValueContext( const Injector& injector, const std::string& name );

      //!
      //! Sets the value to the specified constant value.
      //!
      //! @param constant The constant value.
      //!
      void SetConstant( T1 constant );

      //!
      //! Sets the value to the specified value provider.
      //!
      //! @param provider The value provider.
      //!
      template<class T2>
      void SetProvider( T2 provider );

      //!
      //! Commits the configuration held by the ValueContext to the specified
      //! ResolverCache.
      //!
      //! @param cache The ResolverCache to commit the context to.
      //!
      void Commit( ResolverCache& cache );

   private :
      NamedProvider<T1> namedProvider;
   };


   template<class T1>
   ValueContext<T1>::ValueContext( const Injector& injector, const std::string& name ) 
      : namedProvider(injector, name) {
   }


   template<class T1>
   void ValueContext<T1>::SetConstant( T1 constant ) 
   {
      namedProvider.SetProvider(
         boost::function<T1 ()>(boost::bind(ConstantProxy<T1>, constant))
      );
   }


   template<class T1>
   template<class T2>
   void ValueContext<T1>::SetProvider( T2 provider ) {
      namedProvider.SetProvider(provider);
   }


   template<class T1>
   void ValueContext<T1>::Commit( ResolverCache& cache ) {
      namedProvider.Commit(cache);
   }
}
}

#endif   // IOCPP_VALUECONTEXT_H
